//链接：https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/
//思路“滑动窗口”
//时间复杂度：O(N)
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        /*
        int size = s.size();
        int start_index = 0, end_index = 0;
        int answer = 0;

        unordered_map<char, int> mp;
        for (; start_index < size; ++start_index)
        {
            //start_index跳过连续重复值
            while (start_index + 1 < size && s[start_index] == s[start_index + 1])
            {
                ++start_index;
            }
            //字符串开头没有连续的重复值（或重复至结束），就是说此时的start_index位置及其之前已经处理完（或直接计算）
            if (start_index != 0 && end_index <= start_index)
            {
                end_index = start_index + 1;
            }
            //特殊处理（开头连续重复值，但是不结束），start_index未处理，一次
            static int i = 1;
            if (--i == 0 && start_index < size && s[0] == s[1])
            {
                end_index = start_index;
            }
            //找到重复的就停止，下一次直接从此位置往下找，直到找完
            while (end_index < size && ++mp[s[end_index++]] == 1);
            if (mp[s[end_index - 1]] != 1) { --end_index; }

            int length = end_index - start_index;
            if (length == 0) { length = 1; }
            if (length > answer)
            {
                answer = length;
            }

            if (end_index == size) { break; }//遍历完，提前结束

            mp[s[end_index]] = 1;

            //在下次循环前，清理start_index前的记录
            if (s[start_index] == s[end_index]) { mp[s[start_index]] = 0; }//如果是start_index和end_index 重复
            else { mp.erase(s[start_index]); }
        }
        return answer;
        */

        //更新
        //记录每个字符是否出现过
        unordered_set<char> un_st;
        int size = s.size();
        int left = 0, right = 0, ans = 0;
        for (; left < size; ++left)
        {
            //left右移，移除一个字符
            if (left != 0)
            {
                un_st.erase(s[left - 1]);
            }
            //right右移到出现重复值停下
            while (right < size && !un_st.count(s[right]))
            {
                un_st.insert(s[right]);
                ++right;
            }
            ans = max(ans, right - left);
        }
        return ans;
    }
};